#include"ipc/mutex.h"
#include"cpu/irq.h"
#include"tools/list.h"

void mutex_init(mutex_t* mutex)
{
    mutex->locker_count=0;
    mutex->owner=(task_t*)0;
    list_init(&mutex->wait_list);
}

//上锁
void mutex_lock(mutex_t* mutex)
{
    irq_state state=int_enter_protection();

    task_t* cur= cur_task();
    if(mutex->locker_count==0)
    {
        mutex->locker_count=1;
        mutex->owner=cur;
    }
    else if (mutex->owner==cur)
    {
        mutex->locker_count++;
    }
    else
    {
        task_set_block(cur);
        list_insert_last(&mutex->wait_list,&cur->wait_node);
        task_dispatch();
    }

    int_leave_protection(state);
}

//解锁
void mutex_unlock(mutex_t* mutex)
{
    irq_state state=int_enter_protection();
    
    task_t* cur= cur_task();
    if(mutex->owner==cur)
    {
        if(--mutex->locker_count==0)
        {
            mutex->owner=(task_t*)0;
            if(list_count(&mutex->wait_list))
            {
                list_node* node=list_remove_first(&mutex->wait_list);
                task_t* task=list_node_parent(node,task_t,wait_node);
                task_set_ready(task);

                mutex->locker_count=1;
                mutex->owner=task;

                task_dispatch();
            }
        }
    }
    int_leave_protection(state);
}